#include "Common.h"
#include "ConcurrentAlloc.hpp"
#include <vector>
#include <thread>
#include <atomic>

#define MAXSIZE 16

// 单轮次申请释放次数 线程数 轮次
void BenchmarkConcurrentMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	std::atomic<size_t> malloc_costtime{ 0 };
	std::atomic<size_t> free_costtime{ 0 };

	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&]() {
			std::vector<void*> v;
			v.reserve(ntimes);
			for (size_t j = 0; j < rounds; ++j)
			{
				size_t begin1 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					v.push_back(ConcurrentAlloc(MAXSIZE));

				}
				size_t end1 = clock();
				size_t begin2 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					ConcurrentFree(v[i]);
				}
				size_t end2 = clock();
				v.clear();

				malloc_costtime.fetch_add(end1 - begin1, std::memory_order_relaxed);
				free_costtime.fetch_add(end2 - begin2, std::memory_order_relaxed);
			}
			});
	}
	for (auto& t : vthread)
	{
		t.join();
	}
	printf("%u个线程并发执行%u轮次，每轮次concurrent alloc %u次: 花费：%u ms\n", nworks, rounds, ntimes, malloc_costtime.load());
	printf("%u个线程并发执行%u轮次，每轮次concurrent dealloc %u次: 花费：%u ms\n", nworks, rounds, ntimes, free_costtime.load());
	printf("%u个线程并发concurrent alloc&free %u次，总计花费：%u ms\n", nworks, nworks * rounds * ntimes, malloc_costtime.load() + free_costtime.load());
}

void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	std::atomic<size_t> malloc_costtime{ 0 };
	std::atomic<size_t> free_costtime{ 0 };
	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&]() {
			std::vector<void*> v;
			v.reserve(ntimes);
			for (size_t j = 0; j < rounds; ++j)
			{
				size_t begin1 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					v.push_back(malloc(MAXSIZE));

				}
				size_t end1 = clock();
				size_t begin2 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					free(v[i]);
				}
				size_t end2 = clock();
				v.clear();

				malloc_costtime.fetch_add(end1 - begin1, std::memory_order_relaxed);
				free_costtime.fetch_add(end2 - begin2, std::memory_order_relaxed);
			}
			});
	}
	for (auto& t : vthread)
	{
		t.join();
	}
	printf("%u个线程并发执行%u轮次，每轮次malloc %u次: 花费：%u ms\n", nworks, rounds, ntimes, malloc_costtime.load());
	printf("%u个线程并发执行%u轮次，每轮次free %u次: 花费：%u ms\n", nworks, rounds, ntimes, free_costtime.load());
	printf("%u个线程并发concurrent malloc&free %u次，总计花费：%u ms\n", nworks, nworks * rounds * ntimes, malloc_costtime.load() + free_costtime.load());
}

int main()
{
	size_t nworks = 4; // 线程数
	size_t rounds = 10; // 轮次
	size_t ntimes = 10000; // 次
	printf("==============每轮申请的内存是：%ubyte==============\n", MAXSIZE);
	std::cout << "===========================================================================" << std::endl;
	BenchmarkMalloc(ntimes, nworks, rounds);
	std::cout << "===========================================================================" << std::endl;

	BenchmarkConcurrentMalloc(ntimes, nworks, rounds);
	std::cout << "===========================================================================" << std::endl;

	return 0;
}